package com.myBlog.intercaptor;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.myBlog.enums.Const;
import com.myBlog.enums.LoginMsgCode;
import com.myBlog.pojo.User;
import com.myBlog.repository.UserMapper;
import lombok.Data;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {


    @Data
    @ToString
    public class LoginException extends Exception{
        private int status;
        private String info;

        public LoginException(int status, String info){
            super(status+'-'+info);
            this.status = status;
            this.info = info;
        }
    }

    @Autowired
    private UserMapper userMapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获得cookie
        Cookie[] cookies = request.getCookies();
        // 1.没有cookie信息，则重定向到登录界面
        if (null == cookies) {
            response.setStatus(401);
            throw new LoginException(LoginMsgCode.LoginInfoEmpty.getStatus(), LoginMsgCode.LoginInfoEmpty.getText());
        }
        // 定义cookie，用户的一些登录信息，例如：用户名 等
        String cookie_username = null;
        // 获取cookie里面的一些用户信息
        for (Cookie item : cookies) {
            if ( item.getMaxAge()!=0&&Const.SYSTEM_USER_COOkie.getValue().equals(item.getName()) ) {
                cookie_username = item.getValue();
                break;
            }
        }
        // 2.如果cookie里面没有包含用户的一些登录信息(cookie种存储的用户名)，重新登录
        if (StringUtils.isEmpty(cookie_username)) {
            response.setStatus(401);
            throw new LoginException(LoginMsgCode.LoginInfoEmpty.getStatus(), LoginMsgCode.LoginInfoEmpty.getText());
        }

        String userToken = request.getHeader(Const.USER_TOKEN.getValue());
        // 校验头部token，可以将校验规则写得再复杂一些
        String md5_username = DigestUtils.md5DigestAsHex(cookie_username.getBytes("utf-8")).toUpperCase();
        // 3.校验请求头部token字段不通过，当过期处理，重新登录
        if( !md5_username.equals(userToken) ){
            response.setStatus(401);
            throw new LoginException(LoginMsgCode.LoginTimeOut.getStatus(), LoginMsgCode.LoginTimeOut.getText());
        }

        // 4.获取Session对象，若服务端session种不存在用户名，则设置服务端session对应用户名
        HttpSession session = request.getSession();
        // 获取我们登录后存在session中的用户信息，如果为空，表示session已经过期,重新登录
        String username = (String) session.getAttribute( Const.SYSTEM_USER_SESSION.getValue() );
        if (null == username) {
            LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(User::getUsername,cookie_username);

            User user = userMapper.selectOne(lambdaQueryWrapper);
            if(user==null){
                response.setStatus(401);
                throw new LoginException(LoginMsgCode.LoginTimeOut.getStatus(), LoginMsgCode.LoginTimeOut.getText());
            }else {
                session.setAttribute(Const.SYSTEM_USER_SESSION.getValue(), user.getUsername());
            }
        }

        // 已经登录
        return true;
    }
}
